package com.xuzimian.globaldemo.spring.springmvc.controller;

import com.xuzimian.globaldemo.spring.springmvc.exception.Error;
import com.xuzimian.globaldemo.spring.springmvc.validator.UserValidator;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *  如何继承公共方法的方案。
 *  1.可以当做父类给子类yController继承，从而公用那些@ModelAttribute，@InitBinder 注解的方法。
 *  2.在类上添加@ControllerAdvice 注解，就可以将@InitBinder,@ModelAttribute 注解的方法共享给所有的controller(Handler)
 *      从Spring Mvc4.0开始 @ControllerAdvice 注解 添加了value,basePackages,basePackageClasses,assigableType和 annotations
 *      五个参数，可以通过这些参数选择将这些方法用于哪些Controller,而不是必须所有的Controller.
 *
 * ---------------------------------------------------------------------------------------------------------------------------------
 *
 * @program: global-demo
 * @description: 控制器基类
 * @author: xzm
 * @create: 2019-04-24 16:50
 **/
public class BaseController {


    /**
     * @InitBinder用于在@Controller中标注于方法上，表示为当前控制器注册一个属性编辑器，只对当前的Controller有效。
     * @InitBinder标注的方法必须有一个参数WebDataBinder。所谓的属性编辑器可以理解就是帮助我们完成参数绑定。
     *
     * @InitBinder注释的方法用于初始化Binder,可以在其中做一些Binder初始化的工作,如注册校验器，注册自己的参数编辑器等。
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder){
        //注册编辑器:将空字符转换为Null
        binder.registerCustomEditor(String.class,
                new StringTrimmerEditor(true));

        //注册编辑器:将日期格式化为字符串
        binder.registerCustomEditor(Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));

        //添加校验器:在原有基础上添加
        binder.addValidators(new UserValidator());

        //设置校验器:如果原来有校验器会被替换掉
        //binder.setValidator(new UserValidator());
    }

    /**
     * 继承该控制器的类方法出现异常，将被该方法捕获并处理。
     * @param exception
     * @param response
     * @return
     */
    @ExceptionHandler
    @ResponseBody
    public Object exceptionHandler(Exception exception, HttpServletResponse response) {
        if (exception instanceof Exception) {
            exception.printStackTrace();
            return new Error(0,exception.getMessage());
        }else {
            exception.printStackTrace();
            return new Error(0,"系统发生错误。");
        }
    }


}
